package fpeas.maybe;

import fpeas.function.Function;

public class MaybeUtility
{
	public static <T> Maybe<T> nothing()
	{
		return new Maybe<T>()
		{
			public <R> R accept(final Function<? super T, ? extends R> ifExists, final R reserve)
			{
				return reserve;
			}
		};
	}

	public static <T> Maybe<T> just(final T thing)
	{
		return new Maybe<T>()
		{
			public <R> R accept(final Function<? super T, ? extends R> ifExists, final R reserve)
			{
				return ifExists.run(thing);
			}
		};
	}

	public static <T> Function<T,Maybe<T>> just()
	{
		return new Function<T,Maybe<T>>()
		{
			public Maybe<T> run(final T input)
			{
				return just(input);
			}
		};
	}
	
	public static <T> Maybe<T> fromNullable(final T mayBeNull)
	{
		if (mayBeNull==null)
			return nothing();

		return just(mayBeNull);
	}

	public static <T,R> Function<T,Maybe<R>> justFunction(final Function<T,R> function)
	{
		return new Function<T,Maybe<R>>()
		{
			public Maybe<R> run(final T input)
			{
				return just(function.run(input));
			}
		};
	}

	public static <T,R> Function<Maybe<T>,Maybe<R>> maybeFunction(final Function<T,R> function)
	{
		return new Function<Maybe<T>,Maybe<R>>()
		{
			public Maybe<R> run(final Maybe<T> maybe)
			{
				final Maybe<R> nothing=nothing();
				return maybe.accept(justFunction(function),nothing);
			}
		};
	}
}